import pandas as pd
import numpy as np
import os
from sklearn import svm
from sklearn.metrics import f1_score

kernel_log_data_path = 'memory_sample_kernel_log_round1_a_train.csv'
failure_tag_data_path = 'memory_sample_failure_tag_round1_a_train.csv'
PARENT_FOLDER = 'data' # 数据存放目录

# 计算每个agg_time区间的和
def etl(path, agg_time):
    data = pd.read_csv(os.path.join(PARENT_FOLDER, path))
    # 降低时间精度 向上取整
    data['collect_time'] = pd.to_datetime(data['collect_time']).dt.ceil(agg_time)
    group_data = data.groupby(['serial_number','collect_time'],as_index=False).agg('sum')
    return group_data

# 设置聚合时间粒度
AGG_VALUE = 5
AGG_UNIT = 'min'
AGG_TIME = str(AGG_VALUE)+AGG_UNIT

# 示例仅使用了kernel数据
group_min = etl(kernel_log_data_path, AGG_TIME)

failure_tag = pd.read_csv(os.path.join(PARENT_FOLDER,failure_tag_data_path))
failure_tag['failure_time']= pd.to_datetime(failure_tag['failure_time'])

# 为数据打标
merged_data = pd.merge(group_min,failure_tag[['serial_number','failure_time']],how='left',on=['serial_number'])
merged_data['failure_tag']=(merged_data['failure_time'].notnull()) & ((merged_data['failure_time']-merged_data['collect_time']).dt.seconds <= AGG_VALUE*60)
merged_data['failure_tag']= merged_data['failure_tag']+0
feature_data = merged_data.drop(['serial_number', 'collect_time','manufacturer','vendor','failure_time'], axis=1)

# 负样本下采样
sample_0 = feature_data[feature_data['failure_tag']==0].sample(frac=0.1)
sample = sample_0.append(feature_data[feature_data['failure_tag']==1])

# svm模型训练
clf = svm.SVC()
clf.fit(sample.iloc[:,:-1],sample['failure_tag'])

sample['predict'] = clf.predict(sample.iloc[:,:-1])
print( f1_score(sample['failure_tag'],sample['predict']))

# 测试数据
group_data_test = etl('memory_sample_kernel_log_round1_a_test.csv', AGG_TIME)
group_min_sn_test = pd.DataFrame(group_data_test[['serial_number','collect_time']])
group_min_test = group_data_test.drop(['serial_number', 'collect_time','manufacturer','vendor'], axis=1)

# 模型预测
res = clf.predict(group_min_test)
group_min_sn_test['predict']=res

# 保存结果
group_min_sn_test=group_min_sn_test[group_min_sn_test['predict']==1]
group_min_sn_res = group_min_sn_test.drop('predict',axis=1)
group_min_sn_res.to_csv('memory_predit_res_svm.csv', header=False, index=False)


# 主要思路：
# 以5分钟为一个聚合窗口，计算kernel_log每列的和作为特征，如果机器在5分钟内故障，则标为正样本，剩下的作为负样本，做适量的负样本下采样，训练svm分类模型，输出结果。

# 上述代码 score= 17.1429 ,功能完整,结构清晰,只用了最简单的SVM,继续探索吧！

# 可能的优化方向：
# 1. 相关参数调优
# 2. 打标方法改进
# 3. 目前只用了kernel数据，增加mce和address的特征
# 4. 更多算法，loss等的尝试
# 5. 复杂/衍生特征挖掘
